﻿// This File is part of Innovation Foundry's "QualityHelper Project"
//
// Copyright  2009 Innovation Foundry Pty Ltd
// All rights reserved
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA  02110-1301 USA
// or alternatively it may be downloaded from <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Markup;
using System.Collections.ObjectModel;

using InnovationFoundry.QualityHelper.Silverlight.BLL.Objects;
using InnovationFoundry.QualityHelper.Silverlight.Assets.Resources;

namespace InnovationFoundry.QualityHelper.Silverlight.Controls.ProcedureScroll
{
    public partial class ProcedureScroll : UserControl
    {
        public event ProcedureScrollClickedHandler ProcedureClicked;
        public delegate void ProcedureScrollClickedHandler(object sender, ProcedureScrollClickedArgs args);
        private List<ProcedureObject> procedures = new List<ProcedureObject>();
        private string relationID = null;
        private const double PROCHEIGHT = 70;
        private const double PROCWIDTH = 110;
        private double lastOffset = 0;

        public ProcedureScroll()
        {
            InitializeComponent();
            scrollerProcs.LayoutUpdated += new EventHandler(scrollerProcs_LayoutUpdated);
            scrollerProcs.Loaded += new RoutedEventHandler(ProcedureScroll_Loaded);
        }

        void ProcedureScroll_Loaded(object sender, RoutedEventArgs e)
        {
            refreshLayout();
        }

        void scrollerProcs_LayoutUpdated(object sender, EventArgs e)
        {
            if (lastOffset != scrollerProcs.VerticalOffset)
            {
                lastOffset = scrollerProcs.VerticalOffset;
                RefreshButtons();
            }
        }

        private void refreshLayout()
        {
            if (scrollerProcs.Height != scrollerProcs.ActualHeight && scrollerProcs.ActualHeight != 0)
            {
                this.Height = scrollerProcs.Height + 50;
            }
            RefreshButtons(); 
        }

        public void ClearProcedures()
        {
            procedures.Clear();
            StackProcedures.Children.Clear();
            refreshLayout();
            scrollerProcs.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
        }
        
        public void AddProcedure(ProcedureObject p, string relationID)
        {
            this.relationID = relationID;
            procedures.Add(p);
            DrawProcedures();
            scrollerProcs.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
            refreshLayout();
        }

        public void AddProcedures(IEnumerable<ProcedureObject> procs, string relationID)
        {
            this.relationID = relationID;
            procedures.AddRange(procs);
            DrawProcedures();
            scrollerProcs.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
            refreshLayout();
        }

        private void ShowNextButtons()
        {
            btnNextEnd.Visibility = Visibility.Visible;
            btnNextPage.Visibility = Visibility.Visible;
            btnNext1.Visibility = Visibility.Visible;
        }

        private void HideNextButtons()
        {
            btnNextEnd.Visibility = Visibility.Collapsed;
            btnNextPage.Visibility = Visibility.Collapsed;
            btnNext1.Visibility = Visibility.Collapsed;
        }

        private void RefreshButtons()
        {
            btnNext1.Visibility = Visibility.Collapsed;
            btnNextPage.Visibility = Visibility.Collapsed;
            btnNextEnd.Visibility = Visibility.Collapsed;
            btnPrev1.Visibility = Visibility.Collapsed;
            btnPrevPage.Visibility = Visibility.Collapsed;
            btnPrevEnd.Visibility = Visibility.Collapsed;
            if (procedures.Count == 0)
                return;
            if (StackProcedures.ActualHeight > scrollerProcs.ViewportHeight && scrollerProcs.VerticalOffset > 0)
            {
                btnPrevEnd.Visibility = Visibility.Visible;
                btnPrevPage.Visibility = Visibility.Visible;
                btnPrev1.Visibility = Visibility.Visible;
            }
            if (StackProcedures.ActualHeight > scrollerProcs.ViewportHeight && (scrollerProcs.VerticalOffset < StackProcedures.ActualHeight - scrollerProcs.ViewportHeight))
            {
                btnNextEnd.Visibility = Visibility.Visible;
                btnNextPage.Visibility = Visibility.Visible;
                btnNext1.Visibility = Visibility.Visible;
            }

        }


        private void DrawProcedures() 
        {
            Canvas procedure = new Canvas();
            StackProcedures.Children.Clear();
            for (int i = 0; i < procedures.Count; i++)
            {
                if (procedures[i].Purpose.FlowchartElement == "Diamond")
                {
                    procedure = XamlReader.Load(ControlResources.Diamond) as Canvas;
                    procedure.Width = PROCWIDTH;
                    procedure.Height = PROCHEIGHT + 10;
                    procedure.Margin = new Thickness(35.0, 10.0, 0, 0);
                    procedure.Tag = "diamond";
                    //Rectangle r = diamond.FindName("Rec") as Rectangle;
                    ////r.StrokeThickness = 1;
                    //r.Stroke = new SolidColorBrush(Color.FromArgb(0,255,0,0));
                }
                else if (procedures[i].Purpose.FlowchartElement == "Rectangle" || procedures[i].Purpose.FlowchartElement == "BoxSquare")
                {
                    procedure = XamlReader.Load(ControlResources.Square) as Canvas;
                    procedure.Width = PROCWIDTH;
                    procedure.Height = PROCHEIGHT;
                    procedure.Tag = "square";
                }
                else if (procedures[i].Purpose.FlowchartElement == "RRectangle" || procedures[i].Purpose.FlowchartElement == "BoxRound")
                {
                    procedure = XamlReader.Load(ControlResources.RoundSquare) as Canvas;
                    procedure.Width = PROCWIDTH;
                    procedure.Height = PROCHEIGHT;
                    procedure.Tag = "rsquare";
                }
                //set name
                procedure.Name = procedures[i].ProcedureID;
                Button btn = procedure.FindName("btn") as Button;
                if (btn != null)
                {
                    ToolTipService.SetToolTip(btn, string.Concat(procedures[i].ProcedureDescription, ""));
                    btn.Click += new RoutedEventHandler(procedure_Click);
                }
                //add event (uses click now)
                //procedure.MouseLeftButtonUp += new MouseButtonEventHandler(procedure_MouseLeftButtonUp);
                //set proc name
                TextBlock tb = procedure.FindName("txtName") as TextBlock;
                string[] pNameArray = procedures[i].ProcedureName.Split();
                if (pNameArray.Length > 0)
                    tb.Text = pNameArray[0];
                if (pNameArray.Length > 1)
                    tb.Text += "\n" + pNameArray[1];
                if (pNameArray.Length > 2)
                    tb.Text += "...";



                StackProcedures.Children.Add(procedure);

            }
            refreshLayout();
        }

        void procedure_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //throw new NotImplementedException();
            Canvas c = sender as Canvas;
            if (c == null)
                return;
            TriggerProcedureClick(c);
        }

        void procedure_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            if (btn == null)
                return;
            Canvas c = btn.Parent as Canvas;
            if (c == null)
                return;
            TriggerProcedureClick(c);
        }

        void TriggerProcedureClick(Canvas c)
        {
            if (ProcedureClicked != null)
            {
                ProcedureObject p = getProcedure(c.Name);
                ProcedureScrollClickedArgs args = new ProcedureScrollClickedArgs(p, relationID);
                if (p != null)
                    ProcedureClicked(c, args);
            }
        }

        private ProcedureObject getProcedure(string procedureID)
        {
            foreach (ProcedureObject p in procedures)
            {
                if (p.ProcedureID == procedureID)
                    return p;
            }
            return null;
        }


        public void GotoPrev1()
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.VerticalOffset - PROCHEIGHT);
        }

        public void GotoPrevPage()
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.VerticalOffset - scrollerProcs.ViewportHeight);
        }

        public void GotoPrevTop()
        {
            scrollerProcs.ScrollToVerticalOffset(0);
        }

        public void GotoNext1()
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.VerticalOffset + PROCHEIGHT);
        }

        public void GotoNextPage()
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.VerticalOffset + scrollerProcs.ViewportHeight);
        }

        public void GotoNextEnd()
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.ScrollableHeight);
        }

        public void NavigateToProcedure(int move)
        {
            scrollerProcs.ScrollToVerticalOffset(scrollerProcs.VerticalOffset + (PROCHEIGHT*move));
        }

        public class ProcedureScrollClickedArgs : EventArgs
        {

            private readonly ProcedureObject m_proc;
            private readonly string m_procRelation;

            public ProcedureScrollClickedArgs(ProcedureObject proc, string procRelation)
            {
                m_proc = proc;
                m_procRelation = procRelation;
            }

            public ProcedureObject Procedure
            {
                get { return m_proc; }
            }

            public string ProcedureRelation
            {
                get { return m_procRelation; }
            }

        }

        private void btn_Clicked(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            if (btn != null)
            {
                if (btn.Name == "btnNext1")
                    GotoNext1();
                if (btn.Name == "btnNextPage")
                    GotoNextPage();
                if (btn.Name == "btnNextEnd")
                    GotoNextEnd();
                if (btn.Name == "btnPrev1")
                    GotoPrev1();
                if (btn.Name == "btnPrevPage")
                    GotoPrevPage();
                if (btn.Name == "btnPrevEnd")
                    GotoPrevTop();
            }
        }
    }
}
